package com.hp.team.bookstore.model.catalog;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "PRODUCT")
public class Product extends CatalogItem {

	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinTable(name = "PRODUCT_CATEGORY", joinColumns = { @JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID") }, inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID", referencedColumnName = "ID") })
	private Set<Category> parentCategories;

	@Column(name = "PRICE")
	private double price;

	@Column(name = "PUBLISHER")
	private String publisher;

	@Temporal(TemporalType.DATE)
	@Column(name = "PUBLISHING_DATE")
	private Calendar publishingDate;

	@Column(name = "ISBN")
	private String isbn;

	@Column(name = "AUTHOR")
	private String author;

	@Enumerated(EnumType.STRING)
	@Column(name = "LANGUAGE")
	private Language language;

	@ManyToOne(cascade = { CascadeType.ALL })
	@JoinColumn(name = "VENDOR_ID")
	private Vendor vendor;

	// @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	// @JoinTable(name="PRODUCT_CLASSIFICATION", joinColumns=@JoinColumn(name="product_id"), inverseJoinColumns=@JoinColumn(name="classification_id"))
	// @Type(type="com.hp.team.bookstore.type.ClassificationEnumUserType")
	// @Enumerated(EnumType.STRING)
	@ElementCollection(fetch = FetchType.EAGER)
	private Set<Classification> classifications;

	@ManyToMany(cascade = CascadeType.ALL)
	@JoinTable(name = "PRODUCT_TO_RELATED_PRODUCT", joinColumns = @JoinColumn(name = "product_id"), inverseJoinColumns = @JoinColumn(name = "related_product_id"))
	private Set<Product> relatedProducts = new HashSet<Product>();

	public Set<Category> getParentCategories() {
		return parentCategories;
	}

	public double getPrice() {
		return price;
	}

	public String getPublisher() {
		return publisher;
	}

	public Calendar getPublishingDate() {
		return publishingDate;
	}

	public String getIsbn() {
		return isbn;
	}

	public String getAuthor() {
		return author;
	}

	public Language getLanguage() {
		return language;
	}

	public Vendor getVendor() {
		return vendor;
	}

	public Set<Product> getRelatedProducts() {
		return relatedProducts;
	}

	public void setParentCategories(Set<Category> parentCategories) {
		this.parentCategories = parentCategories;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public void setPublishingDate(Calendar publishingDate) {
		this.publishingDate = publishingDate;
	}

	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public void setLanguage(Language language) {
		this.language = language;
	}

	public void setVendor(Vendor vendor) {
		this.vendor = vendor;
	}

	public void setRelatedProducts(Set<Product> relatedProducts) {
		this.relatedProducts = relatedProducts;
	}

	public Set<Classification> getClassifications() {
		return classifications;
	}

	public void setClassifications(Set<Classification> classifications) {
		this.classifications = classifications;
	}

	@Override
	public String toString() {
		return getName() + ", " + getAuthor();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Product) {
			Product otherProduct = (Product) obj;
			if (getId() > 0) {
				return this.getId() == otherProduct.getId();
			} else {
				return this.getName().equals(otherProduct.getName())
						&& this.getAuthor().equals(otherProduct.getAuthor());
			}
		}
		return false;
	}
}
